import re
import json
import requests

def convert_angular_menu_to_ruo_yi(angular_menu):
    result_routes = []

    def clean_load_string(load_str):
        if not load_str:
            return '[]'

        # 1. 移除所有注释（单行和多行）
        cleaned = re.sub(r'//.*$', '', load_str, flags=re.MULTILINE)  # 单行注释
        cleaned = re.sub(r'/\*[\s\S]*?\*/', '', cleaned)  # 多行注释

        # 2. 标准化引号并修复键名
        cleaned = cleaned.replace("'", '"')  # 单引号转双引号
        cleaned = re.sub(r'([a-zA-Z_][a-zA-Z0-9_]*):', r'"\1":', cleaned)  # 键名加双引号

        # 3. 修复尾随逗号
        cleaned = re.sub(r',\s*([\]\}])', r'\1', cleaned)

        # 4. 修复连续逗号
        cleaned = re.sub(r',(\s*,)+', ',', cleaned)

        # 5. 确保数组元素正确分隔
        cleaned = re.sub(r',\s*\]', ']', cleaned)
        cleaned = re.sub(r',\s*\}', '}', cleaned)

        # 6. 移除多余空格
        cleaned = re.sub(r'\s+', ' ', cleaned).strip()

        return cleaned

    def parse_load(load_str):
        if not load_str:
            return []

        file_js = []
        try:
            cleaned_load = clean_load_string(load_str)
            load_config = json.loads(cleaned_load)

            if not isinstance(load_config, list):
                load_config = [load_config]

            for item in load_config:
                if "name" in item and "files" in item:
                    for f in item["files"]:
                        lower_file = f.lower()
                        if f.endswith('.js') and ('controller' in lower_file or 'ctrl' in lower_file):
                            file_js.append(f)
            return file_js
        except Exception as e:
            print(f'解析load字段失败: {load_str}, 错误: {e}')
            return []

    def convert_alias_to_name(alias):
        if not alias:
            return ''

        if '.' in alias:
            parts = alias.split('.')[1:]
            converted_parts = []
            for part in parts:
                words = part.split('_')
                camel_case = words[0] + ''.join(w.capitalize() for w in words[1:])
                converted_parts.append(camel_case.replace('_', ''))
            return ''.join(converted_parts)
        else:
            words = alias.split('_')
            return words[0] + ''.join(w.capitalize() for w in words[1:]).replace('_', '')

    def process_menu(menu, parent_route=None, level=0):
        # 安全获取menuUrl，处理None值
        menu_url = menu.get("menuUrl", "") or ""

        if menu.get("enableMenu") == 0:
            if parent_route is not None:
                file_js = parse_load(menu.get("load", ""))
                page_info = {
                    "title": menu.get("name", ""),
                    "path": menu_url,
                    "icon": menu.get("menuIcon", "el-icon-menu"),
                    "htmlUrl": menu.get("templateUrl", ""),
                    "alias": menu.get("alias", "")
                }
                if file_js:
                    page_info["fileJs"] = file_js

                if "meta" not in parent_route:
                    parent_route["meta"] = {}
                if "subPages" not in parent_route["meta"]:
                    parent_route["meta"]["subPages"] = []

                parent_route["meta"]["subPages"].append(page_info)
            return None

        # 处理组件路径
        templateUrl = menu.get("templateUrl", "")
        component_path = re.sub(r'^bms/views/|^views/', '', templateUrl.replace('.html', '')) if templateUrl else ""

        # 构建路由对象
        route = {
            "path": component_path,
            "name": convert_alias_to_name(menu.get("alias", "")),
            "meta": {
                "title": menu.get("name", ""),
                "icon": menu.get("menuIcon", "el-icon-menu"),
                "htmlUrl": templateUrl
            }
        }

        file_js = parse_load(menu.get("load", ""))
        if file_js:
            route["meta"]["fileJs"] = file_js

        # 处理子菜单
        children = menu.get("children", [])
        has_children = False
        if children:
            route["children"] = []
            for child in children:
                child_route = process_menu(child, route, level + 1)
                if child_route:
                    route["children"].append(child_route)
                    has_children = True

            if not has_children:
                del route["children"]

        # 设置组件类型和路径
        if has_children:
            if level == 0:  # 顶级菜单
                route["component"] = "Layout"
                route["path"] = menu_url
                if route.get("children") and route["path"]:
                    first_child = route["children"][0]
                    # 确保重定向路径格式正确
                    redirect_path = f"{route['path']}/{first_child['path']}"
                    # 移除可能的双斜杠
                    redirect_path = redirect_path.replace("//", "/")
                    route["redirect"] = redirect_path
            elif level == 1:  # 二级菜单
                route["component"] = "ParentView"
                # 安全处理None值
                route["path"] = menu_url.lstrip('/') if menu_url else ""
            else:  # 三级及以上
                route["component"] = component_path or "EmptyLayout"
        else:
            route["component"] = component_path or "Layout"

        # 路径格式化 - 确保不会对None值操作
        if level == 0 and route["path"] and not route["path"].startswith('/'):
            route["path"] = '/' + route["path"]
        if route["path"] and route["path"].endswith('/'):
            route["path"] = route["path"].rstrip('/')

        return route

    # 处理顶级菜单
    for top_menu in angular_menu:
        converted = process_menu(top_menu, None, 0)
        if converted:
            result_routes.append(converted)

    return result_routes

def get_routers(base_url, auth_token, tenant_id):
    """
    获取并转换路由数据

    参数:
    base_url -- API基础地址
    auth_token -- 认证token (用于Authorization头)
    tenant_id -- 租户ID (用于tenant-id头)
    """
    try:
        # 构建API请求URL
        url = f"{base_url}/portal/sys/sysMenu/v1/getCurrentUserMenu"
        params = {"menuAlias": "system.front_menu"}

        # 构建请求头
        headers = {
            "Authorization": f"Bearer {auth_token}",
            "tenant-id": tenant_id,
            "Content-Type": "application/json"
        }

        # 发送GET请求
        print(f"\n发送请求到: {url}")
        print(f"请求头: {json.dumps(headers, indent=2)}")

        response = requests.get(
            url,
            params=params,
            headers=headers
        )
        response.raise_for_status()  # 检查HTTP错误

        # 解析JSON响应
        data = response.json()
        print("\n原始API响应状态:", data.get("state", "未知"))

        # 安全打印原始数据
        value_data = data.get("value", [])
        print("原始API数据:", json.dumps(value_data, indent=2, ensure_ascii=False) if value_data else "空")

        if data.get("state"):
            res_data = data.get("value", [])
            if res_data:
                ruoyi_routes = convert_angular_menu_to_ruo_yi(res_data)
                print("\n转换后的路由结构:", json.dumps(ruoyi_routes, indent=2, ensure_ascii=False))
                return {"data": ruoyi_routes}
            return {"data": []}
        else:
            print("API返回状态错误:", data)
            return {"data": []}
    except requests.exceptions.RequestException as e:
        print(f"\n请求失败: {e}")
        print(f"响应状态码: {e.response.status_code if e.response else '无响应'}")
        if e.response:
            print(f"错误响应内容: {e.response.text[:500]}")  # 只打印前500个字符
        raise
    except json.JSONDecodeError as e:
        print(f"\nJSON解析失败: {e}")
        print(f"响应内容: {response.text[:500] if 'response' in locals() else '无响应'}")
        raise
    except Exception as e:
        print(f"\n未知错误: {e}")
        raise

if __name__ == "__main__":
    # ====== 配置参数 ======
    # 根据实际情况修改以下值
    BASE_URL = "http://uatbms.einyun.com"  # API基础地址
    AUTH_TOKEN = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJKWkZXWV9hZG1pbi5iNzBhYmQyZC1hZTQ5LTRmNTAtODdiNC0yN2RkN2MwMzBhMjYiLCJ0ZW5hbnRJZCI6ImI3MGFiZDJkLWFlNDktNGY1MC04N2I0LTI3ZGQ3YzAzMGEyNiIsImV4cCI6MTc0OTI3ODg2MywiaWF0IjoxNzQ5MTkyNDYzfQ.J4VUbeWB319OfvSLKJeq3QE-jnZ_qp-52qHYbwYPBNF_zn4h3CTEWoAvbnwUT1tC9AC1q6jOJtgh-JkUWKQ1Eg"     # 认证token
    TENANT_ID = "b70abd2d-ae49-4f50-87b4-27dd7c030a26"            # 租户ID

    print("====== 开始路由转换程序 ======")

    try:
        # 获取并转换路由
        # print(f"\n使用配置:")
        # print(f"  API地址: {BASE_URL}")
        # print(f"  租户ID: {TENANT_ID}")
        # print(f"  Token: {AUTH_TOKEN[:15]}...")  # 只显示token前15位

        result = get_routers(BASE_URL, AUTH_TOKEN, TENANT_ID)

        # 输出最终结果
        print("\n====== 最终结果 ======")
        print(json.dumps(result, indent=2, ensure_ascii=False))

        # 保存结果到11.json文件
        filename = "11.json"
        with open(filename, "w", encoding="utf-8") as f:
            json.dump(result, f, indent=2, ensure_ascii=False)
            print(f"\n结果已保存到 {filename}")

        print("\n====== 程序执行完成 ======")

    except Exception as e:
        print(f"\n!!! 程序执行出错: {e}")
        import traceback
        traceback.print_exc()  # 打印完整的错误堆栈
        print("====== 程序异常终止 ======")
